package com.redis.util;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

/**
 * @Author Tanyu
 * @Date 2020/6/1 10:37
 * @Description
 * redisTemplate.opsForList();//操作list
 * redisTemplate.opsForValue();//操作字符串
 * redisTemplate.opsForCluster();//集群时使用
 * redisTemplate.opsForGeo();//地理位置时使用
 * redisTemplate.opsForHash();//操作hash
 * redisTemplate.opsForSet();//操作set
 * redisTemplate.opsForZSet();//操作有序set
 * @Version 1.0
 */
@Component
public class RedisUtils {

  @Autowired
  private RedisTemplate<String, String> redisTemplate;

  /**
   * 读取缓存
   */
  public String getKey(final String key) {
    return redisTemplate.opsForValue().get(key);
  }

  /**
   * 写入缓存
   */
  public Boolean setKey(final String key, String value) {
    Boolean result = false;

    try {
      redisTemplate.opsForValue().set(key, value);
      result = Boolean.TRUE;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return result;
  }


  /**
   * 设置key/value值，并且可以设置超时时间。
   */
  public Boolean setKey(final String key, String value, int time, TimeUnit unit) {
    Boolean result = false;

    try {
      redisTemplate.opsForValue().set(key, value, time, unit);
      result = Boolean.TRUE;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return result;
  }

  /**
   * 同时设置多个key/value
   */
  public Boolean multiSet(Map<String, String> map) {
    Boolean result = false;

    try {
      redisTemplate.opsForValue().multiSet(map);
      result = Boolean.TRUE;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return result;
  }

  /**
   * 同时获取多个key/value
   */
  public List<String> multiGet(Collection<String> keys) {
    return redisTemplate.opsForValue().multiGet(keys);
  }

  /**
   * 操作取号器
   */
  public long incr(String key, long delta) {
    return redisTemplate.opsForValue().increment(key, delta);
  }

  /**
   * 跟新缓存
   */
  public Boolean getAndSet(final String key, String value) {
    Boolean result = Boolean.FALSE;
    try {
      redisTemplate.opsForValue().set(key, value);
      result = Boolean.TRUE;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return result;
  }

  /**
   * 删除key
   */
  public Boolean delete(final String key) {
    Boolean result = Boolean.FALSE;
    try {
      redisTemplate.delete(key);
      result = Boolean.TRUE;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return result;
  }

  /**
   * 操作队列，在高并发的情况下，如果同时上千个线程同时操作数据库， 数据库很可能会因此而宕机。这个时候我们可以利用redis队列，进行排队依次写入数据库。
   * 利用lpush和rpop，可以形成一个queue。
   */

  public void lpush(String key, String value) {
    redisTemplate.opsForList().leftPush(key, value);
  }

  public List<String> range(String key, int start, int end) {
    return redisTemplate.opsForList().range(key, start, end);
  }

  public Object rpop(String key) {
    return redisTemplate.opsForList().rightPop(key);
  }

  /**
   * 有时候我们不光希望保存key/value， 也希望缓存某个对象，比如用户所有数据到redis。 我们可以使用Redis的Hash数据结构来缓存。
   */
  public void setHash(String key, Map<String, Object> map) {
    redisTemplate.opsForHash().putAll(key, map);
  }

  public Object getHash(String key, String prop) {
    return redisTemplate.opsForHash().get(key, prop);
  }

  public Map getHashAll(String key) {
    Map map = new HashMap();
    map.put("keys", redisTemplate.opsForHash().keys(key));
    map.put("vals", redisTemplate.opsForHash().values(key));
    return map;
  }

  /**
   * 如果我们需要一个小型的消息中间件，可以选择redis的订阅/发布来实现。
   */


}
